package com.yipinhouse.signing.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yipinhouse.common.enums.HouseStatusEnum;
import com.yipinhouse.common.enums.HouseTypeEnum;
import com.yipinhouse.common.exception.HouseException;
import com.yipinhouse.employee.client.BrokerInfoQueryClient;
import com.yipinhouse.employee.client.result.BrokerInfoResult;
import com.yipinhouse.house.client.*;
import com.yipinhouse.signing.common.IntentionMoneyStatusEnum;
import com.yipinhouse.signing.infra.config.AlipayConfig;
import com.yipinhouse.signing.infra.model.IntentionMoney;
import com.yipinhouse.signing.infra.mapper.IntentionMoneyMapper;
import com.yipinhouse.signing.infra.model.IntentionMoneyFlowing;
import com.yipinhouse.signing.service.IntentionMoneyFlowingService;
import com.yipinhouse.signing.service.IntentionMoneyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yipinhouse.signing.service.dto.IntentionMoneyDto;
import com.yipinhouse.signing.service.param.IntentionMoneyServiceParam;
import com.yipinhouse.user.client.UserQueryClient;
import com.yipinhouse.user.client.result.UserInfoResult;
import io.seata.spring.annotation.GlobalTransactional;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.redisson.RedissonMultiLock;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.messaging.Message;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 意向金 服务实现类
 * </p>
 *
 * @author WangCong
 * @since 2022-12-01
 */
@Service
public class IntentionMoneyServiceImpl extends ServiceImpl<IntentionMoneyMapper, IntentionMoney> implements IntentionMoneyService {

    @Resource
    private ResoldApartmentQueryClient resoldApartmentQueryClient;

    @Resource
    private ResoldHouseQueryClient resoldHouseQueryClient;

    @Resource
    private NewHouseQueryClient newHouseQueryClient;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private ResoldApartmentManageClient resoldApartmentManageClient;

    @Resource
    private ResoldHouseManageClient resoldHouseManageClient;

    @Resource
    private RocketMQTemplate rocketMQTemplate;

    @Resource
    private UserQueryClient userQueryClient;

    @Resource
    private BrokerInfoQueryClient brokerInfoQueryClient;

    @Resource
    private IntentionMoneyFlowingService intentionMoneyFlowingService;
    /**
     * 新增意向金记录
     *
     * @param param
     * @return
     */
    @Override
    @GlobalTransactional
    public IntentionMoneyDto insertIntentionMoney(IntentionMoneyServiceParam param) throws InterruptedException {
        //1.1检查用户是否实名
        if (!userQueryClient.verifyIdentity(param.getUserId())) throw new HouseException("用户未实名认证，无法新建意向金",6104);
        //1.2检查房源状态是否可以预定
        String houseStatus = null;
        if (param.getHouseType().equals(HouseTypeEnum.NEW_HOUSE.getCode())){
            //新房
            houseStatus = (String) newHouseQueryClient.checkHouseStatus(param.getHouseId()).getData();
        }else if (param.getHouseType().equals(HouseTypeEnum.SECOND_HAND_HOUSING.getCode())){
            //二手房
            houseStatus = (String) resoldApartmentQueryClient.checkHouseStatus(param.getHouseId()).getData();
        }else if (param.getHouseType().equals(HouseTypeEnum.RENTAL_HOUSING.getCode())){
            //出租房
            houseStatus = resoldHouseQueryClient.checkHouseStatus(param.getHouseId()).getData();
        }else throw new HouseException("房源类型错误！",6100);
        if (houseStatus!= null && !houseStatus.equals(HouseStatusEnum.SALE.getCode())) throw new HouseException("该房源不可锁定",6101);
        //2.锁定房源（修改房源状态为已预订）
        RLock lock = redissonClient.getLock("yipinhouse:lock" + param.getHouseId() + param.getHouseType());
        RedissonMultiLock rml = new RedissonMultiLock(lock);
        boolean a = false;
        try {
            a = rml.tryLock(60,60, TimeUnit.SECONDS);
            if (a){
                //枷锁成功修改状态
                if (param.getHouseType().equals(HouseTypeEnum.NEW_HOUSE.getCode())){
                    //新房
                    newHouseQueryClient.orderHouse(param.getHouseId());
                }else if (param.getHouseType().equals(HouseTypeEnum.SECOND_HAND_HOUSING.getCode())){
                    //二手房
                    resoldApartmentManageClient.orderHouse(param.getHouseId());
                }else if (param.getHouseType().equals(HouseTypeEnum.RENTAL_HOUSING.getCode())){
                    //出租房
                    resoldHouseManageClient.orderHouse(param.getHouseId());
                }
            }
        } finally {
            if (rml != null ) rml.unlock();
        }
        //3.插入意向金记录
        IntentionMoney intentionMoney = new IntentionMoney();
        intentionMoney.setHouseId(param.getHouseId());
        intentionMoney.setBrokerId(param.getBrokerId());
        intentionMoney.setUserId(param.getUserId());
        intentionMoney.setHouseType(param.getHouseType());
        intentionMoney.setAmount(param.getAmount());
        intentionMoney.setPayMethod("支付宝");
        intentionMoney.setStatus(IntentionMoneyStatusEnum.TO_BE_PAID.getCode());
        //3.2雪花id
        String num = "YP" + IdUtil.getSnowflake(1,1).nextId();
        intentionMoney.setIntentionMoneyNum(num);
        save(intentionMoney);
        //4.mq发送延时消息回查支付状态
        Message<String> message = MessageBuilder.withPayload(num).build();
        rocketMQTemplate.syncSend("yipinhouse-intentionMoney-cancel",message,10000,6);
        //5.返回记录数据
        BrokerInfoResult broker = brokerInfoQueryClient.getBrokerInfo(param.getBrokerId()).getData();
        UserInfoResult user = userQueryClient.checkInfo(param.getUserId()).getData();
        IntentionMoneyDto intentionMoneyDto = new IntentionMoneyDto();
        intentionMoneyDto.setId(intentionMoney.getId());
        intentionMoneyDto.setBrokerName(broker.getRealName());
        intentionMoneyDto.setBrokerId(intentionMoney.getBrokerId());
        intentionMoneyDto.setUserName(user.getRealname());
        intentionMoneyDto.setAmount(intentionMoney.getAmount()+"");
        intentionMoneyDto.setStatus(intentionMoney.getStatus());
        //TODO 查询地址包括门牌号
        //intentionMoneyDto.setHouseAddress();
        return intentionMoneyDto;
    }

    @Override
    public String pay(String intentionMoneyNum) throws UnsupportedEncodingException, AlipayApiException {
        //查询订单状态
        IntentionMoney intentionMoney = getOne(new QueryWrapper<IntentionMoney>().eq("intention_money_num",intentionMoneyNum));
        if (intentionMoney != null && intentionMoney.getStatus().equals(IntentionMoneyStatusEnum.TO_BE_PAID.getCode())) {
            //获得初始化的AlipayClient
            AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);

            //设置请求参数
            AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
            alipayRequest.setReturnUrl(AlipayConfig.return_url);
            alipayRequest.setNotifyUrl(AlipayConfig.notify_url);

            //商户订单号，商户网站订单系统中唯一订单号，必填
            String out_trade_no = new String(intentionMoneyNum.getBytes("ISO-8859-1"), "UTF-8");
            //付款金额，必填
            String total_amount = new String(intentionMoney.getAmount().setScale(2, BigDecimal.ROUND_HALF_UP).toString().getBytes("ISO-8859-1"), "UTF-8");
            //订单名称，必填
            String subject = "意向金";
            //商品描述，可空
            String body = "";

            alipayRequest.setBizContent("{\"out_trade_no\":\"" + out_trade_no + "\","
                    + "\"total_amount\":\"" + total_amount + "\","
                    + "\"subject\":\"" + subject + "\","
                    + "\"body\":\"" + body + "\","
                    + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");

            //请求
            String result = alipayClient.pageExecute(alipayRequest).getBody();
            return result;
        }
        return null;
    }

    @Override
    public void payok(Integer id) {
        //1修改意向金记录状态
        IntentionMoney intentionMoney = getById(id);
        intentionMoney.setPayMethod("支付宝");
        intentionMoney.setPayTime(new Date());
        intentionMoney.setStatus(IntentionMoneyStatusEnum.PAID.getCode());
        updateById(intentionMoney);
        //1.2 TODO 发送定时任务，几天后执行签约回查
        //3生成流水记录
        IntentionMoneyFlowing intentionMoneyFlowing = new IntentionMoneyFlowing();
        intentionMoneyFlowing.setIntentionMoneyId(intentionMoney.getId());
        intentionMoneyFlowing.setAmount(intentionMoney.getAmount());
        intentionMoneyFlowing.setCreateTime(new Date());
        intentionMoneyFlowing.setStatus("入账");
        intentionMoneyFlowingService.save(intentionMoneyFlowing);
    }


}
